package com.uzhie.web.service.listener;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.uzhie.component.GpsComponent;
import com.uzhie.component.VideoAnalyseComponent;
import com.uzhie.component.VideoComponent;
import com.uzhie.component.WarningComponent;
import com.uzhie.jt808.jt1078.entity.JT_1005;
import com.uzhie.jt808.jt1078.entity.JT_1205;
import com.uzhie.jt808.jt1078.entity.JT_9206;
import com.uzhie.jt808.JT808Constant;
import com.uzhie.jt808.msg.entity.JT_0200;
import com.uzhie.jt808.msg.entity.JT_0800;
import com.uzhie.jt808.msg.entity.JT_200.JS_0200;
import com.uzhie.web.module.Video;
import com.uzhie.web.service.PictureService;
import com.uzhie.util.ConcurrentCollection;
import io.netty.buffer.ByteBufUtil;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.jms.BytesMessage;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import java.io.IOException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by zhenghao on 2017/7/4.
 */
//@Component(value = "consumerMessageListener")
public class MQReceiveServiceBak implements MQReceiveService {

    private Logger logger = Logger.getLogger(this.getClass());
    private ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    private Timer positionTimer = new Timer("MQReceiveServicePositionTimer", true);
    private final String param = "simNumber";
    private final String driver = "driver";
    private long overTime;
    private long checkTime;

    @Autowired
    GpsComponent gpsComponent;
    @Autowired
    WarningComponent warningComponent;
    @Autowired
    VideoAnalyseComponent videoAnalyseComponent;
    @Autowired
    PictureService pictureService;

    @Autowired
    private VideoComponent videoComponent;


    public MQReceiveServiceBak() {
        logger.info("MQReceiveServiceBak 被加载,当前实例 " + this);
        logger.setLevel(Level.FATAL);
    }

    public void setOverTime(long overTime) {
        this.overTime = overTime;
    }

    public void setCheckTime(long checkTime) {
        this.checkTime = checkTime;
    }

    @Override
    public void onMessage(Message message) {
        final Message msg = message;
        try {
            logger.info("收到activeMQ的通知消息");
            switch (message.getIntProperty("type")) {
                case JT808Constant.MSG_ID.DEV_REQ_POSITION:
                    logger.fatal("收到位置信息消息");
                    cachedThreadPool.execute(() -> handlerJT_0200(msg));
                    break;
                case JT808Constant.MSG_ID.PLA_REQ_PLAYBACK_CATALOG:
                    logger.fatal("收到远程目录消息");
                    handlerCatalog(msg);
                    break;
                case JT808Constant.MSG_ID.DEV_REQ_MEDIA_DATA:
                    logger.fatal("收到图片上传信息");
                    handlerPic(msg);
                    break;
                case JT808Constant.MSG_ID.DEV_REQ_PASSENGER:
                    logger.fatal("收到乘客流量信息");
                    handlerPassenger(msg);
                    break;
                case JT808Constant.MSG_ID.DEV_REQ_FILE_UPLOAD_COMPLETE:
                    logger.fatal("收到FTP文件上传信息");
                    handlerFtpUp(msg);
                    break;
                default:
                    break;
            }
        } catch (JMSException e) {
            e.printStackTrace();
            logger.error("处理MQ消息错误：" + e.getMessage());
        }

    }

    //处理远程目录回传
    private void handlerCatalog(Message message) {
        try {
            String simNumber = message.getStringProperty(param);
            logger.info(" 收到了远程目录--->");
            Thread thread = ConcurrentCollection.getInstance().getThread(simNumber);
            logger.info("当前收到的ID是 : " + simNumber + "  ~~~  ConcurrentCollection 的线程容器长度为 : " + ConcurrentCollection.getInstance().getThreadSize());
            //如果线程已经被释放,则不进行下面的激活操作
            if (thread == null) {
                logger.error("~~~~~消息ID为 [" + simNumber + "] 的Thread 为 null ~~~~");
                ConcurrentCollection.getInstance().removeResult(simNumber);
                return;
            }
            logger.info("当前线程ID :[" + thread.getId() + "]");
            //获取消息体内容
            BytesMessage bytesMessage = (BytesMessage) message;
            byte[] body = new byte[(int) bytesMessage.getBodyLength()];
            logger.info(" 远程目录消息长度 : [" + bytesMessage.getBodyLength() + "]--->");
            bytesMessage.readBytes(body);
            logger.info("远程目录body消息内容为 : [" + body.toString() + " ]--->");
            JT_1205 order = new JT_1205(body);
            JSONArray arr = (JSONArray) JSON.toJSON(order.getCatalog());
            ConcurrentCollection.getInstance().setResult(simNumber, arr);
            //激活当前线程等待状态
            synchronized (thread) {
                logger.info("线程 [" + thread.getId() + "] 开始激活");
                thread.notifyAll();
                logger.info("线程 [" + thread.getId() + "] 被激活");
                return;
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }

    //处理位置信息
    private void handlerJT_0200(Message msg) {
        try {
            BytesMessage bytesMessage = (BytesMessage) msg;
            if (bytesMessage.getBodyLength() > 0) {
                logger.info(" 收到了位置信息--->");
                byte[] body = new byte[(int) bytesMessage.getBodyLength()];
                logger.info(" 位置信息消息长度 : [" + bytesMessage.getBodyLength() + "]--->");
                bytesMessage.readBytes(body);
                String mSimNumber = msg.getStringProperty(param);
                logger.info(" 位置信息的@车辆内置SIM卡@ 卡号为 : [" + mSimNumber + "] --->");
                JT_0200 order = new JT_0200();
                order.ReadFromBytes(body);
                logger.info(" 转换后的 位置信息内容为 : [ " + order.toString() + " ] --->");
                handlerPosition(order, mSimNumber);
                handlerWarns(order, mSimNumber);
            }
        } catch (JMSException e) {
            logger.error("位置信息消息转义错误", e);
        }
    }

    //处理客流量上传
    private void handlerPassenger(Message message) {
        try {
            String mSimNumber = message.getStringProperty(param);
            logger.info(" 客流量消息@车辆内置SIM卡@ 卡号为 : [" + mSimNumber + "] --->");
            //获取消息体内容
            BytesMessage bytesMessage = (BytesMessage) message;
            byte[] body = new byte[(int) bytesMessage.getBodyLength()];
            logger.info(" 远程客流量消息长度 : [" + bytesMessage.getBodyLength() + "]--->");
            bytesMessage.readBytes(body);
            logger.info("客流量消息body消息内容为 : [" + body.toString() + " ]--->");
            JT_1005 order = new JT_1005();
            order.ReadFromBytes(body);
            logger.info(" 转换后的客流量内容为 : [ " + order.toString() + " ] --->");
            videoAnalyseComponent.addPassenger(order, mSimNumber);
        } catch (Exception e) {
            logger.error("客流量上传异常", e);
        }
    }

    private void handlerWarns(JT_0200 order, String simNumber) {
        cachedThreadPool.execute(() -> {
            if (order.isMediaWarning() != 0) {
                warningComponent.addWarning(order, simNumber);
            }
            if (order.isJSWarning()) {
                logger.info("有苏标报警 正在处理");
                JS_0200 js0200 = (JS_0200) order;
                warningComponent.addJSWarning(js0200, simNumber);
            }
            warningComponent.addWarningCollection(simNumber);
        });
    }

    private void handlerPosition(JT_0200 order, String simNumber) {
        cachedThreadPool.execute(() -> gpsComponent.addGpsRecord(simNumber, order));
    }


    private void handlerPic(Message msg) {
        try {
            BytesMessage bytesMessage = (BytesMessage) msg;
            logger.info(" 收到了图片上传信息--->");
            byte[] body = new byte[(int) bytesMessage.getBodyLength()];
            logger.info(" 图片上传消息长度 : [" + bytesMessage.getBodyLength() + "]--->");
            bytesMessage.readBytes(body);
            logger.info("图片上传body消息内容为 : [" + body.toString() + " ]--->");
            String mSimNumber = msg.getStringProperty(param);
            logger.info(" 位置信息的@车辆内置SIM卡@ 卡号为 : [" + mSimNumber + "] --->");
            JT_0800 order = new JT_0800(body);
            pictureService.addPicture(mSimNumber, order);

        } catch (JMSException | IOException e) {
            logger.error("图片保存异常", e);
        }
    }

    private void handlerFtpUp(Message msg) {
        try {
            BytesMessage bytesMessage = (BytesMessage) msg;
            byte[] body = new byte[(int) bytesMessage.getBodyLength()];
            bytesMessage.readBytes(body);
            logger.info("收到文件上传消息体：" + ByteBufUtil.hexDump(body));
            JT_9206 jt_9206 = new JT_9206();
            jt_9206.ReadFromBytes(body);
            Video video = new Video();
            video.setStoragePosition(jt_9206.getFilePath());
            DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
            video.setBeginTime(dateFormat.parse(jt_9206.getStartTime()));
            video.setEndTime(dateFormat.parse(jt_9206.getEndTime()));
            video.setChannel(jt_9206.getChannel() & 0XFF);
            video.setStatus(1);
            videoComponent.addVideo(video);
        } catch (Exception e) {
            logger.error("FTP文件上传完成消息解析异常", e);
        }
    }

    /**
     * 定位信息存储task
     */
    protected void positionTask() {
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
                try {
                    gpsComponent.gpsInsertTask();
                } catch (Exception e) {
                    logger.error("位置信息批量存储异常", e);
                }
            }
        };
        positionTimer.schedule(task, checkTime, checkTime);
        logger.warn("位置信息服务启用成功");
    }


    /**
     * 定位存储任务销毁
     */
    protected void onDestroy() {
        if (positionTimer != null) {
            positionTimer.cancel();
            positionTimer = null;
            logger.warn("位置信息服务停止成功");
        }
    }

}
